library ieee;
	use ieee.std_logic_1164.all;
 	use ieee.std_logic_unsigned.all;
 	use ieee.std_logic_arith.all;
 	use ieee.math_real.all; 
 	use ieee.numeric_std.all;

library work;
    use work.router_pack.all;
    use work.env_pack.all;    

-------------------------------------------------------------------------
    
entity collector_if is

port(
    -- General Signals: --
    RESET   : in std_logic;
    CLK     : in std_logic;
    
    -- Input Port i/f: --
    RI      : in std_logic;
    AI      : out std_logic;
    DI      : in std_logic_vector(flit_size_c-1 downto 0);
    
    -- Packet Output --
    PACKET_RECEIVED : out std_logic;
    SL              : out std_logic_vector(msl_ind_width-1 downto 0);
    PACKET_SIZE     : out std_logic_vector(e_packet_size_width_c-1 downto 0);
    PACKET_ID       : out std_logic_vector(e_packet_id_width_c-1 downto 0)
);

end collector_if;

-------------------------------------------------------------------------

architecture collector_if_arch of collector_if is

-- Internal Signals --

--   signal flit_count   : std_logic_vector(e_packet_size_width_c-1 downto 0);
   
   subtype flit_count_t is std_logic_vector(e_packet_size_width_c-1 downto 0);
   type flit_count_arr_t is array(num_of_sl_con-1 downto 0, num_of_vc_con-1 downto 0) of flit_count_t;
   signal flit_count_arr : flit_count_arr_t;
   
   type packet_id_arr_t is array(num_of_sl_con-1 downto 0, num_of_vc_con-1 downto 0) of std_logic_vector(e_packet_id_width_c-1 downto 0);
--   signal packet_id_arr : packet_id_arr_t;

begin
    
   flit_rx: process(RESET, CLK)
   variable ack_ind      				: std_logic;
   variable packet_received_in 	: std_logic;
   variable flit_sl 				: integer;
   variable flit_vc				: integer;
   variable packet_id_arr 				: packet_id_arr_t;
   begin
      
      if (CLK'event and CLK='1') then
         
         packet_received_in := '0';
         
         if (RESET = '1') then
            ack_ind := '0';
         
         -- if there's a new incoming flit
         elsif ((RI='1') and (ack_ind='0')) then
         
         		flit_sl := conv_integer(DI(flit_sl_format_h downto flit_sl_format_l));
         		flit_vc := conv_integer(DI(flit_v_format_h downto flit_v_format_h-vc_width+1));
            
            -- if this is a header flit
            if (DI(flit_type_format_h downto flit_type_format_l) = "01") then
               flit_count_arr(flit_sl, flit_vc) <= conv_std_logic_vector(1, e_packet_size_width_c);
            
            -- if this is a body or a tail flit
            else
            
               -- If haven't received the PacketID yet
               if (flit_count_arr(flit_sl, flit_vc) < e_min_flit_count_c) then

                  case conv_integer(flit_count_arr(flit_sl, flit_vc)) is
                     when 1 => packet_id_arr(flit_sl, flit_vc)(1*e_flit_data_width_c-1 downto 0*e_flit_data_width_c) := DI(e_flit_data_msb_c downto 0);
                     when 2 => packet_id_arr(flit_sl, flit_vc)(2*e_flit_data_width_c-1 downto 1*e_flit_data_width_c) := DI(e_flit_data_msb_c downto 0);                     
--                     when "0010" => PACKET_ID(2*e_flit_data_width_c-1 downto 1*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "0011" => PACKET_ID(3*e_flit_data_width_c-1 downto 2*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "0100" => PACKET_ID(4*e_flit_data_width_c-1 downto 3*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                     
--                     when "0101" => PACKET_ID(5*e_flit_data_width_c-1 downto 4*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                     
--                     when "0110" => PACKET_ID(6*e_flit_data_width_c-1 downto 5*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                     
--                     when "0111" => PACKET_ID(7*e_flit_data_width_c-1 downto 6*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                     
--                     when "1000" => PACKET_ID(8*e_flit_data_width_c-1 downto 7*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "1001" => PACKET_ID(9*e_flit_data_width_c-1 downto 8*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "1010" => PACKET_ID(10*e_flit_data_width_c-1 downto 9*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                                                                                        
--                     when "1011" => PACKET_ID(11*e_flit_data_width_c-1 downto 10*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);                         
--                     when "1100" => PACKET_ID(12*e_flit_data_width_c-1 downto 11*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "1101" => PACKET_ID(13*e_flit_data_width_c-1 downto 12*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "1110" => PACKET_ID(14*e_flit_data_width_c-1 downto 13*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
--                     when "1111" => PACKET_ID(15*e_flit_data_width_c-1 downto 14*e_flit_data_width_c) <= DI(e_flit_data_msb_c downto 0);
                  		 when others => packet_id_arr(flit_sl, flit_vc)(1*e_flit_data_width_c-1 downto 0*e_flit_data_width_c) := DI(e_flit_data_msb_c downto 0);
                  end case;
               
               end if; -- (flit_count < e_min_flit_count_c)
               
               flit_count_arr(flit_sl, flit_vc) <= flit_count_arr(flit_sl, flit_vc) + 1;
            end if; -- if this is a body or a tail flit
            
            -- if this is a tail flit
            if (DI(flit_type_format_h downto flit_type_format_l) = "10") then
               packet_received_in := '1';
               PACKET_SIZE <= flit_count_arr(flit_sl, flit_vc) + 1;
               PACKET_ID <= packet_id_arr(flit_sl, flit_vc);
               SL <= conv_std_logic_vector(flit_sl, msl_ind_width);
            end if;
            
            -- acknowledge the new flit
            ack_ind := '1';
         
         -- if flit request was deasserted
         elsif (RI='0') then
            
            -- deassert the ack   
            ack_ind := '0';
            
         end if; --((RI='1') and (AI='0'))
         
         AI <= ack_ind;
         PACKET_RECEIVED <= packet_received_in;
         
      end if; -- (CLK'event and CLK='1')
      
   end process;
end collector_if_arch;
